import { describe, it, expect } from 'vitest';
import {
  fullySpecifiedUnmapper,
  multiTrailingUnmapper,
  multiTrailingUnmapperOne,
  noTrailingUnmapper,
  onlyTrailingUnmapper,
  singleTrailingUnmapper,
} from '../../../../../src/arbitrary/_internals/mappers/EntitiesToIPv6';

describe('fullySpecifiedUnmapper', () => {
  it.each`
    ip                                           | expected
    ${'0123:5678:9abc:ef01:2345:6789:128.0.0.1'} | ${[['0123', '5678', '9abc', 'ef01', '2345', '6789'], '128.0.0.1']}
    ${'0123:5678:9abc:ef01:2345:6789:0000:ffff'} | ${[['0123', '5678', '9abc', 'ef01', '2345', '6789'], '0000:ffff']}
    ${'0:56:9abc:ef01:234:67:8.8.8.8'}           | ${[['0', '56', '9abc', 'ef01', '234', '67'], '8.8.8.8']}
    ${'0:56:9abc:ef01:234:67:0:f'}               | ${[['0', '56', '9abc', 'ef01', '234', '67'], '0:f']}
  `('should properly unmap IPv6 $ip', ({ ip, expected }) => {
    // Arrange / Act
    const out = fullySpecifiedUnmapper(ip);

    // Assert
    expect(out).toEqual(expected);
  });
});

describe('onlyTrailingUnmapper', () => {
  it.each`
    ip                                        | expected
    ${'::5678:9abc:ef01:2345:6789:128.0.0.1'} | ${[['5678', '9abc', 'ef01', '2345', '6789'], '128.0.0.1']}
    ${'::5678:9abc:ef01:2345:6789:0000:ffff'} | ${[['5678', '9abc', 'ef01', '2345', '6789'], '0000:ffff']}
  `('should properly unmap IPv6 $ip', ({ ip, expected }) => {
    // Arrange / Act
    const out = onlyTrailingUnmapper(ip);

    // Assert
    expect(out).toEqual(expected);
  });
});

describe('multiTrailingUnmapper', () => {
  it.each`
    ip                                       | expected
    ${'::9abc:ef01:2345:6789:128.0.0.1'}     | ${[[], ['9abc', 'ef01', '2345', '6789'], '128.0.0.1']}
    ${'::9abc:ef01:2345:6789:0000:ffff'}     | ${[[], ['9abc', 'ef01', '2345', '6789'], '0000:ffff']}
    ${'5678::9abc:ef01:2345:6789:128.0.0.1'} | ${[['5678'], ['9abc', 'ef01', '2345', '6789'], '128.0.0.1']}
    ${'5678::9abc:ef01:2345:6789:0000:ffff'} | ${[['5678'], ['9abc', 'ef01', '2345', '6789'], '0000:ffff']}
    ${'::ef01:2345:6789:128.0.0.1'}          | ${[[], ['ef01', '2345', '6789'], '128.0.0.1']}
    ${'::ef01:2345:6789:0000:ffff'}          | ${[[], ['ef01', '2345', '6789'], '0000:ffff']}
    ${'9abc::ef01:2345:6789:128.0.0.1'}      | ${[['9abc'], ['ef01', '2345', '6789'], '128.0.0.1']}
    ${'9abc::ef01:2345:6789:0000:ffff'}      | ${[['9abc'], ['ef01', '2345', '6789'], '0000:ffff']}
    ${'5678:9abc::ef01:2345:6789:128.0.0.1'} | ${[['5678', '9abc'], ['ef01', '2345', '6789'], '128.0.0.1']}
    ${'5678:9abc::ef01:2345:6789:0000:ffff'} | ${[['5678', '9abc'], ['ef01', '2345', '6789'], '0000:ffff']}
    ${'::2345:6789:128.0.0.1'}               | ${[[], ['2345', '6789'], '128.0.0.1']}
    ${'::2345:6789:0000:ffff'}               | ${[[], ['2345', '6789'], '0000:ffff']}
    ${'ef01::2345:6789:128.0.0.1'}           | ${[['ef01'], ['2345', '6789'], '128.0.0.1']}
    ${'ef01::2345:6789:0000:ffff'}           | ${[['ef01'], ['2345', '6789'], '0000:ffff']}
    ${'9abc:ef01::2345:6789:128.0.0.1'}      | ${[['9abc', 'ef01'], ['2345', '6789'], '128.0.0.1']}
    ${'9abc:ef01::2345:6789:0000:ffff'}      | ${[['9abc', 'ef01'], ['2345', '6789'], '0000:ffff']}
    ${'5678:9abc:ef01::2345:6789:128.0.0.1'} | ${[['5678', '9abc', 'ef01'], ['2345', '6789'], '128.0.0.1']}
    ${'5678:9abc:ef01::2345:6789:0000:ffff'} | ${[['5678', '9abc', 'ef01'], ['2345', '6789'], '0000:ffff']}
  `('should properly unmap IPv6 $ip', ({ ip, expected }) => {
    // Arrange / Act
    const out = multiTrailingUnmapper(ip);

    // Assert
    expect(out).toEqual(expected);
  });
});

describe('multiTrailingUnmapperOne', () => {
  it.each`
    ip                                       | expected
    ${'::6789:128.0.0.1'}                    | ${[[], '6789', '128.0.0.1']}
    ${'::6789:0000:ffff'}                    | ${[[], '6789', '0000:ffff']}
    ${'2345::6789:128.0.0.1'}                | ${[['2345'], '6789', '128.0.0.1']}
    ${'2345::6789:0000:ffff'}                | ${[['2345'], '6789', '0000:ffff']}
    ${'ef01:2345::6789:128.0.0.1'}           | ${[['ef01', '2345'], '6789', '128.0.0.1']}
    ${'ef01:2345::6789:0000:ffff'}           | ${[['ef01', '2345'], '6789', '0000:ffff']}
    ${'9abc:ef01:2345::6789:128.0.0.1'}      | ${[['9abc', 'ef01', '2345'], '6789', '128.0.0.1']}
    ${'9abc:ef01:2345::6789:0000:ffff'}      | ${[['9abc', 'ef01', '2345'], '6789', '0000:ffff']}
    ${'5678:9abc:ef01:2345::6789:128.0.0.1'} | ${[['5678', '9abc', 'ef01', '2345'], '6789', '128.0.0.1']}
    ${'5678:9abc:ef01:2345::6789:0000:ffff'} | ${[['5678', '9abc', 'ef01', '2345'], '6789', '0000:ffff']}
  `('should properly unmap IPv6 $ip', ({ ip, expected }) => {
    // Arrange / Act
    const out = multiTrailingUnmapperOne(ip);

    // Assert
    expect(out).toEqual(expected);
  });
});

describe('singleTrailingUnmapper', () => {
  it.each`
    ip                                       | expected
    ${'::128.0.0.1'}                         | ${[[], '128.0.0.1']}
    ${'::0000:ffff'}                         | ${[[], '0000:ffff']}
    ${'2345::128.0.0.1'}                     | ${[['2345'], '128.0.0.1']}
    ${'2345::0000:ffff'}                     | ${[['2345'], '0000:ffff']}
    ${'ef01:2345::128.0.0.1'}                | ${[['ef01', '2345'], '128.0.0.1']}
    ${'ef01:2345::0000:ffff'}                | ${[['ef01', '2345'], '0000:ffff']}
    ${'9abc:ef01:2345::128.0.0.1'}           | ${[['9abc', 'ef01', '2345'], '128.0.0.1']}
    ${'9abc:ef01:2345::0000:ffff'}           | ${[['9abc', 'ef01', '2345'], '0000:ffff']}
    ${'5678:9abc:ef01:2345::128.0.0.1'}      | ${[['5678', '9abc', 'ef01', '2345'], '128.0.0.1']}
    ${'5678:9abc:ef01:2345::0000:ffff'}      | ${[['5678', '9abc', 'ef01', '2345'], '0000:ffff']}
    ${'0123:5678:9abc:ef01:2345::128.0.0.1'} | ${[['0123', '5678', '9abc', 'ef01', '2345'], '128.0.0.1']}
    ${'0123:5678:9abc:ef01:2345::0000:ffff'} | ${[['0123', '5678', '9abc', 'ef01', '2345'], '0000:ffff']}
    ${'::0123'}                              | ${[[], '0123']}
    ${'6789::0123'}                          | ${[['6789'], '0123']}
    ${'2345:6789::0123'}                     | ${[['2345', '6789'], '0123']}
    ${'ef01:2345:6789::0123'}                | ${[['ef01', '2345', '6789'], '0123']}
    ${'9abc:ef01:2345:6789::0123'}           | ${[['9abc', 'ef01', '2345', '6789'], '0123']}
    ${'5678:9abc:ef01:2345:6789::0123'}      | ${[['5678', '9abc', 'ef01', '2345', '6789'], '0123']}
    ${'0123:5678:9abc:ef01:2345:6789::0123'} | ${[['0123', '5678', '9abc', 'ef01', '2345', '6789'], '0123']}
  `('should properly unmap IPv6 $ip', ({ ip, expected }) => {
    // Arrange / Act
    const out = singleTrailingUnmapper(ip);

    // Assert
    expect(out).toEqual(expected);
  });
});

describe('noTrailingUnmapper', () => {
  it.each`
    ip                                        | expected
    ${'::'}                                   | ${[[]]}
    ${'0123::'}                               | ${[['0123']]}
    ${'6789:0123::'}                          | ${[['6789', '0123']]}
    ${'2345:6789:0123::'}                     | ${[['2345', '6789', '0123']]}
    ${'ef01:2345:6789:0123::'}                | ${[['ef01', '2345', '6789', '0123']]}
    ${'9abc:ef01:2345:6789:0123::'}           | ${[['9abc', 'ef01', '2345', '6789', '0123']]}
    ${'5678:9abc:ef01:2345:6789:0123::'}      | ${[['5678', '9abc', 'ef01', '2345', '6789', '0123']]}
    ${'0123:5678:9abc:ef01:2345:6789:0123::'} | ${[['0123', '5678', '9abc', 'ef01', '2345', '6789', '0123']]}
  `('should properly unmap IPv6 $ip', ({ ip, expected }) => {
    // Arrange / Act
    const out = noTrailingUnmapper(ip);

    // Assert
    expect(out).toEqual(expected);
  });
});
